<?php

declare (strict_types=1);

namespace magein\think\pay\controller;

use magein\pay\PayConfig;
use magein\pay\PayException;
use magein\pay\PayFactory;
use magein\pay\Payment;
use magein\pay\platform\AliPay;
use magein\pay\platform\WxPay;
use magein\think\pay\model\PayOrderModel;
use magein\think\utils\ApiResponse;
use think\App;
use think\facade\Request;
use think\Response;
use think\response\Redirect;
use think\response\View;

class PayController
{
    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * @var Payment
     */
    protected $payment = null;

    public function __construct(App $app)
    {
        $this->app = $app;
        $this->request = $this->app->request;
        $this->payment = $this->app->payment;
    }

    /**
     * 收银台
     * @return void
     */
    public function center()
    {
        if ($this->request->isAjax()) {

            $data = $this->request->post();

            $data['sign'] = PayFactory::singer()->create($data);

            $result = $this->payment->unify($data);

            $data = $result->getData();
            if (isset($data['oauth'])) {
                return redirect($data['oauth']);
            }

            return ApiResponse::result($result);
        }

        $data = $this->request->get();
        $platforms = PayConfig::platforms();
        $list = [];
        foreach ($platforms as $key => $platform) {
            $list[] = [
                'key' => $key,
                'name' => $platform['name'],
                'icon' => $platform['icon'],
            ];
        }

        return view(__DIR__ . '/../view/center.html', [
            'pay_data' => $data,
            'platforms' => $list
        ]);
    }

    /**
     * @return Response
     */
    public function qrcode(): Response
    {
        $data = $this->request->post();

        return ApiResponse::result($this->payment->qrcode($data));
    }

    /**
     * @return Response
     */
    public function qrcodeAvailable(): Response
    {
        $pay_no = $this->request->get('pay_no');

        return ApiResponse::success($this->payment->qrcodeAvailable($pay_no));
    }

    /**
     * @return Response|Redirect
     */
    public function scan()
    {
        $pay_no = $this->request->get('pay_no');

        $result = $this->payment->scan($pay_no);

        $data = $result->getData();
        if ($result->getCode()) {
            return view(__DIR__ . '/../view/error.html', $result->toArray());
        }

        $platform_id = $data['platform_id'] ?? '';
        if ($platform_id) {
            $trade_type = $data['trade_type'] ?? '';

            if ($platform_id == WxPay::getPlatformName() && $trade_type == WxPay::TRADE_TYPE_JSAPI) {
                return view(__DIR__ . '/../view/jsapi.html', $data);
            }

            if ($platform_id == AliPay::getPlatformName()) {

                if ($trade_type == AliPay::TRADE_TYPE_WAP) {
                    return $data['pay_data'];
                }

                if ($trade_type == AliPay::TRADE_TYPE_FAST) {
                    return redirect($data['pay_data']);
                }
            }
        }

        if (isset($data['oauth'])) {
            return redirect($data['oauth']);
        }

        return ApiResponse::result($result);
    }

    /**
     * 统一下单
     * @return Response
     */
    public function unify(): Response
    {
        $data = $this->request->post();

        return ApiResponse::result($this->payment->unify($data));
    }

    /**
     * 异步通知
     * @param Request $request
     * @return string
     */
    public function notify(Request $request): string
    {
        $pay_no = $request::route('pay_no');
        /**
         * 1. 这里不能使用ApiResponse去响应，不然会导致微信收不到正确的响应信息，导致重复通知
         * 2. 微信支付发送的xml不用接手，使用的easywechat框架接手的
         * 3. 支付宝使用的接收参数的格式使用post方式
         */
        return $this->payment->notify($pay_no, $request::post());
    }

    /**
     * @param Request $request
     * @return Redirect
     */
    public function success(Request $request): Redirect
    {
        $pay_no = $request::route('pay_no');

        $url = $this->payment->success($pay_no);

        return redirect($url);
    }

    /**
     * @param Request $request
     * @return View
     */
    public function oauth(Request $request): View
    {
        $account = $request::route('account');
        $pay_no = $request::route('pay_no');
        $code = $request::param('code');

        $result = $this->payment->oauth($code, $account, $pay_no);

        $data = $result->getData();
        if ($result->getCode()) {
            return view(__DIR__ . '/../view/error.html', $result->toArray());
        }

        return view(__DIR__ . '/../view/jsapi.html', $data);
    }

    /**
     * @param Request $request
     * @return Response
     */
    public function query(Request $request): Response
    {
        $pay_no = $request::param('pay_no');
        $type = (int)$request::param('type', 0);

        return ApiResponse::result($this->payment->query($pay_no, $type));
    }

    /**
     * @param Request $request
     * @return Response|View
     */
    public function test(Request $request)
    {
        if ($request::isAjax()) {

            $type = $request::param('type');
            $post = $request::post();

            try {

                $post['sign'] = PayFactory::singer()->create($post);

                if ($type === 'qrcode') {
                    $result = $this->payment->qrcode($post);
                } else {
                    $result = $this->payment->unify($post);
                }

            } catch (PayException $exception) {
                $result = $exception->toResult();
            }

            return ApiResponse::result($result);

        } else {

            $scenes = PayOrderModel::translateScene();

            return view(__DIR__ . '/../view/test.html', [
                'scenes' => $scenes
            ]);
        }
    }
}